package com.hyts.distlock.util;

import com.hyts.distlock.config.LockConfig;
import com.hyts.jlogger.util.StringUtils;
import com.hyts.properties.manager.PropertyManager;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.util.Pool;

import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;

/**
 * project-name:coffice-toolbox
 * package-name:com.hyts.distlock.util
 * author:Libo/Alex
 * create-date:2019-05-27 23:44
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于:
 */
public class JedisPoolProvider {

    public final static Logger logger = Logger.getLogger(JedisPoolProvider.class.getName());

    private static Pool<Jedis> pool;

    static {
        try {
            init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化连接池
     */
    private static void init() throws Exception {

        PropertyManager propertyManager = PropertyManager.getInstance().settingDefaultConfigurationName(LockConfig.DEFAULT_JEDIS_PROPERTIES);
        logger.info("初始化Redis连接池。");
        //创建jedis池配置实例
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

        //加载jedis池配置项
        Integer poolMaxTotal = propertyManager.getValue2Number("redis.pool.maxTotal",100);
        jedisPoolConfig.setMaxTotal(poolMaxTotal);

        Integer poolMaxIdle = propertyManager.getValue2Number("redis.pool.maxIdle",300);
        jedisPoolConfig.setMaxIdle(poolMaxIdle);

        Long poolMaxWaitMillis = (long)propertyManager.getValue2Number("redis.pool.maxWaitMillis",5000);
        jedisPoolConfig.setMaxWaitMillis(poolMaxWaitMillis);

        logger.info(String.format("poolMaxTotal: %s, poolMaxIdle: %s", poolMaxTotal, poolMaxIdle));

        String connectMode = propertyManager.getValue2Text("redis.connectMode","single");
        logger.info(String.format("connectMode : %s.", connectMode));



        if ("single".equals(connectMode)) {
            //单机
            String host = propertyManager.getValue2Text("redis.pool.host","127.0.0.1");
            String port = propertyManager.getValue2Text("redis.pool.port","6379");
            logger.info(String.format("hostPort - %s.", host + ":" + port));
            pool = new JedisPool(jedisPoolConfig, host, Integer.valueOf(port));
        } else if ("sentinel".equals(connectMode)) {
            // 集群
            String hostPort = propertyManager.getValue2Text("redis.hostPort");

            if (StringUtils.isNull(hostPort)) {
                throw new RuntimeException("redis配置文件未配置主机-端口集。");
            }

            logger.info(String.format("hostPort - %s.", hostPort));

            //根据配置实例化jedis池
            String[] hostPortSet = hostPort.split(",");

            Set<String> sentinels = new HashSet<String>();

            for (String hostPortInfo : hostPortSet) {
                sentinels.add(hostPortInfo);
            }
            pool = new JedisSentinelPool("master", sentinels, jedisPoolConfig);
        }
    }

    /**
     * 获取Jedis对象
     * 使用完成后，必须调用returnResource归还到连接池中
     *
     * @return Jedis对象
     */
    public static Jedis getResource() {
        Jedis jedis = pool.getResource();
        logger.info("获得Redis连接：" + jedis);
        return jedis;
    }

    /**
     * 获取Jedis对象
     * 使用完成后，必须调用returnResource归还到连接池中
     *
     * @param db Redis数据库序号
     * @return Jedis对象
     */
    public static Jedis getResource(int db) {
        Jedis jedis = pool.getResource();
        jedis.select(db);
        logger.info("获得Redis连接：" + jedis);
        return jedis;
    }

    /**
     * 归还Redis连接到连接池
     *
     * @param jedis Jedis对象
     */
    public static void returnResource(Jedis jedis) {
        if (jedis != null) {
            pool.returnResource(jedis);
            logger.info("归还Redis连接到连接池：" + jedis);
        }
    }

    public static void destroy() throws Exception {
        pool.destroy();
    }
}
